#pragma once

#include "Sourcecode/Renderer/Camera.h"

namespace Hazal
{
	class CSceneCamera : public CCamera
	{
	public:
		enum class ProjectionType
		{
			Perspective = 0,
			Orthographic = 1,
		};

	public:
		CSceneCamera();

		virtual ~CSceneCamera();

	public:
		/// <summary>
		/// Set orthographic projection matrix
		/// </summary>
		/// <param name="fSize"></param>
		/// <param name="fNearClip"></param>
		/// <param name="fFarCilp"></param>
		void SetOrthographic(float fSize, float fNearClip, float fFarCilp);

		/// <summary>
		/// Set perspective projection matrix
		/// </summary>
		/// <param name="fVerticalFOV"></param>
		/// <param name="fNearClip"></param>
		/// <param name="fFarClip"></param>
		void SetPerspective(float fVerticalFOV, float fNearClip, float fFarClip);

		void SetViewportSize(uint32_t unWidth, uint32_t unHeight);

		/// <summary>
		/// Set Orthographic zoom level
		/// </summary>
		/// <param name="fSize"></param>
		inline void SetOrthographicSize(float fSize) { m_fOrthographicSize = fSize;  RecaculateProjection(); }

		/// <summary>
		/// Get Orthographic zoom level
		/// </summary>
		/// <returns></returns>
		inline float GetOrthographicSize() const { return m_fOrthographicSize; }

		/// <summary>
		/// Get orthographic near clip
		/// </summary>
		/// <returns></returns>
		inline float GetOrthographicNearClip() const { return m_fOrthographicNear; }

		/// <summary>
		/// Set orthographic near clip
		/// </summary>
		/// <param name="fNearClip"></param>
		inline void SetOrthographicNearClip(float fNearClip) { m_fOrthographicNear = fNearClip; RecaculateProjection(); }

		/// <summary>
		/// Get orthographic far clip
		/// </summary>
		/// <returns></returns>
		inline float GetOrthographicFarClip() const { return m_fOrthographicFar; }

		/// <summary>
		/// Set orthographic far clip
		/// </summary>
		/// <param name="fFarClip"></param>
		inline void SetOrthographicFarClip(float fFarClip) { m_fOrthographicFar = fFarClip; RecaculateProjection(); }

		/// <summary>
		/// Set camera projection type
		/// </summary>
		/// <param name="nType"></param>
		inline void SetProjectionType(uint32_t nType) { m_eProjectionType = (ProjectionType)nType; RecaculateProjection(); }

		/// <summary>
		/// Set perspective vertical fov
		/// </summary>
		/// <param name="fFOV"></param>
		inline void SetPerspectiveVerticalFOV(float fFOV) { m_fPerspectiveFOV = fFOV; RecaculateProjection(); }

		/// <summary>
		/// Get perspective vertical fov
		/// </summary>
		inline float GetPerspectiveVerticalFOV() { return m_fPerspectiveFOV; }

		/// <summary>
		/// Set perspective near clip
		/// </summary>
		/// <param name="fNearClip"></param>
		inline void SetPerspectiveNearClip(float fNearClip) { m_fPerspectiveNear = fNearClip; RecaculateProjection(); }

		/// <summary>
		/// Get perspective near clip
		/// </summary>
		inline float GetPerspectiveNearClip() { return m_fPerspectiveNear; }

		/// <summary>
		/// Set perspective far clip
		/// </summary>
		/// <param name="fFarClip"></param>
		inline void SetPerspectiveFarClip(float fFarClip) { m_fPerspectiveFar = fFarClip; RecaculateProjection(); }

		/// <summary>
		/// Get perspective far clip
		/// </summary>
		inline float GetPerspectiveFarClip() { return m_fPerspectiveFar; }


		/// <summary>
		/// Get camera projection type
		/// </summary>
		inline ProjectionType GetProjectionType() const { return m_eProjectionType; }

	private:
		void RecaculateProjection();

	private:
		ProjectionType m_eProjectionType = ProjectionType::Orthographic;

		float m_fOrthographicSize = 10.0f;
		float m_fOrthographicNear = -1.0f;
		float m_fOrthographicFar = 1.0f;
		
		float m_fPerspectiveFOV = glm::radians(45.0f);
		float m_fPerspectiveNear = 0.01f;
		float m_fPerspectiveFar = 1000.0f;

		float m_fAspectRadio = 1.0f;
	};
}
